import random
import string
import tkinter as tk
from tkinter import ttk, messagebox

class PasswordGenerator:
    def __init__(self, root):
        self.root = root
        self.root.title("密码生成器")
        self.root.geometry("500x420")
        self.root.resizable(False, False)
        
        # 设置样式
        self.style = ttk.Style()
        self.style.configure('TButton', font=('微软雅黑', 10))
        self.style.configure('TLabel', font=('微软雅黑', 10))
        self.style.configure('TCheckbutton', font=('微软雅黑', 10))
        
        # 主标题
        self.title_label = ttk.Label(root, text="强密码生成器", font=('微软雅黑', 16, 'bold'))
        self.title_label.pack(pady=10)
        
        # 创建主框架
        self.main_frame = ttk.Frame(root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
        
        # 密码长度设置
        self.length_frame = ttk.Frame(self.main_frame)
        self.length_frame.pack(fill=tk.X, pady=5)
        
        self.length_label = ttk.Label(self.length_frame, text="密码长度:")
        self.length_label.pack(side=tk.LEFT)
        
        self.length_var = tk.IntVar(value=12)
        self.length_scale = ttk.Scale(self.length_frame, from_=6, to=30, variable=self.length_var, 
                                     orient=tk.HORIZONTAL, length=250, command=self.update_length_label)
        self.length_scale.pack(side=tk.LEFT, padx=10)
        
        self.length_value_label = ttk.Label(self.length_frame, text="12")
        self.length_value_label.pack(side=tk.LEFT)
        
        # 字符选项
        self.options_frame = ttk.LabelFrame(self.main_frame, text="包含字符")
        self.options_frame.pack(fill=tk.X, pady=10)
        
        # 使用变量存储复选框状态
        self.uppercase_var = tk.BooleanVar(value=True)
        self.lowercase_var = tk.BooleanVar(value=True)
        self.digits_var = tk.BooleanVar(value=True)
        self.symbols_var = tk.BooleanVar(value=True)
        
        # 添加复选框
        self.uppercase_check = ttk.Checkbutton(self.options_frame, text="大写字母 (A-Z)", 
                                              variable=self.uppercase_var)
        self.uppercase_check.grid(row=0, column=0, sticky=tk.W, padx=10, pady=5)
        
        self.lowercase_check = ttk.Checkbutton(self.options_frame, text="小写字母 (a-z)", 
                                              variable=self.lowercase_var)
        self.lowercase_check.grid(row=1, column=0, sticky=tk.W, padx=10, pady=5)
        
        self.digits_check = ttk.Checkbutton(self.options_frame, text="数字 (0-9)", 
                                           variable=self.digits_var)
        self.digits_check.grid(row=0, column=1, sticky=tk.W, padx=10, pady=5)
        
        self.symbols_check = ttk.Checkbutton(self.options_frame, text="特殊符号 (!@#$%等)", 
                                            variable=self.symbols_var)
        self.symbols_check.grid(row=1, column=1, sticky=tk.W, padx=10, pady=5)
        
        # 排除相似字符
        self.exclude_frame = ttk.Frame(self.main_frame)
        self.exclude_frame.pack(fill=tk.X, pady=5)
        
        self.exclude_similar_var = tk.BooleanVar(value=False)
        self.exclude_similar = ttk.Checkbutton(self.exclude_frame, 
                                              text="排除相似字符 (i, l, 1, L, o, 0, O)", 
                                              variable=self.exclude_similar_var)
        self.exclude_similar.pack(anchor=tk.W)
        
        # 排除重复字符
        self.exclude_duplicate_var = tk.BooleanVar(value=False)
        self.exclude_duplicate = ttk.Checkbutton(self.exclude_frame, 
                                                text="排除重复字符", 
                                                variable=self.exclude_duplicate_var)
        self.exclude_duplicate.pack(anchor=tk.W)
        
        # 排除空格
        self.exclude_space_var = tk.BooleanVar(value=True)
        self.exclude_space = ttk.Checkbutton(self.exclude_frame, 
                                           text="排除空格", 
                                           variable=self.exclude_space_var)
        self.exclude_space.pack(anchor=tk.W)
        
        # 生成按钮
        self.generate_button = ttk.Button(self.main_frame, text="生成密码", command=self.generate_password)
        self.generate_button.pack(pady=10)
        
        # 密码显示区域
        self.password_frame = ttk.Frame(self.main_frame)
        self.password_frame.pack(fill=tk.X, pady=5)
        
        self.password_var = tk.StringVar()
        self.password_entry = ttk.Entry(self.password_frame, textvariable=self.password_var, font=('Courier New', 12), width=40)
        self.password_entry.pack(side=tk.LEFT, padx=(0, 10))
        
        # 复制密码按钮
        self.copy_button = ttk.Button(self.password_frame, text="复制", command=self.copy_password)
        self.copy_button.pack(side=tk.LEFT)
        
        # 密码强度
        self.strength_frame = ttk.Frame(self.main_frame)
        self.strength_frame.pack(fill=tk.X, pady=5)
        
        self.strength_label = ttk.Label(self.strength_frame, text="密码强度:", font=('微软雅黑', 10))
        self.strength_label.pack(side=tk.LEFT)
        
        self.strength_var = tk.StringVar(value="")
        self.strength_value = ttk.Label(self.strength_frame, textvariable=self.strength_var, font=('微软雅黑', 10, 'bold'))
        self.strength_value.pack(side=tk.LEFT, padx=5)
        
        # 生成一个初始密码
        self.generate_password()
        
    def update_length_label(self, *args):
        self.length_value_label.config(text=str(self.length_var.get()))
        
    def generate_password(self):
        # 获取所有选项
        length = self.length_var.get()
        use_uppercase = self.uppercase_var.get()
        use_lowercase = self.lowercase_var.get()
        use_digits = self.digits_var.get()
        use_symbols = self.symbols_var.get()
        exclude_similar = self.exclude_similar_var.get()
        exclude_duplicate = self.exclude_duplicate_var.get()
        exclude_space = self.exclude_space_var.get()
        
        # 验证至少选择了一种字符类型
        if not any([use_uppercase, use_lowercase, use_digits, use_symbols]):
            messagebox.showwarning("警告", "请至少选择一种字符类型")
            return
        
        # 创建字符集
        chars = ""
        
        if use_uppercase:
            chars += string.ascii_uppercase
        if use_lowercase:
            chars += string.ascii_lowercase
        if use_digits:
            chars += string.digits
        if use_symbols:
            chars += string.punctuation
        if not exclude_space:
            chars += " "
            
        # 排除相似字符
        if exclude_similar:
            for char in "il1Lo0O":
                chars = chars.replace(char, "")
                
        # 验证字符集不为空
        if not chars:
            messagebox.showwarning("警告", "根据您的设置，没有可用的字符")
            return
            
        # 生成密码
        if exclude_duplicate:
            # 如果排除重复字符，并且长度超过可用字符数量
            if length > len(chars):
                messagebox.showwarning("警告", f"设置了排除重复字符，但密码长度({length})超过了可用字符数量({len(chars)})")
                return
            password = ''.join(random.sample(chars, length))
        else:
            password = ''.join(random.choice(chars) for _ in range(length))
        
        # 确保密码包含所选的所有字符类型
        contains_uppercase = any(c in string.ascii_uppercase for c in password) if use_uppercase else True
        contains_lowercase = any(c in string.ascii_lowercase for c in password) if use_lowercase else True
        contains_digit = any(c in string.digits for c in password) if use_digits else True
        contains_symbol = any(c in string.punctuation for c in password) if use_symbols else True
        
        # 如果不满足条件，重新生成
        if not all([contains_uppercase, contains_lowercase, contains_digit, contains_symbol]):
            return self.generate_password()
            
        # 更新密码显示
        self.password_var.set(password)
        
        # 评估密码强度
        self.evaluate_password_strength(password)
        
    def evaluate_password_strength(self, password):
        # 简单的密码强度评估
        strength = 0
        
        # 长度得分 (最高 5 分)
        if len(password) >= 8:
            strength += 1
        if len(password) >= 12:
            strength += 1
        if len(password) >= 16:
            strength += 1
        if len(password) >= 20:
            strength += 1
        if len(password) >= 24:
            strength += 1
            
        # 字符类型得分 (每种类型 1 分，最高 4 分)
        if any(c in string.ascii_lowercase for c in password):
            strength += 1
        if any(c in string.ascii_uppercase for c in password):
            strength += 1
        if any(c in string.digits for c in password):
            strength += 1
        if any(c in string.punctuation for c in password):
            strength += 1
            
        # 根据得分设置强度级别
        if strength <= 4:
            self.strength_var.set("弱")
            self.strength_value.config(foreground="red")
        elif strength <= 6:
            self.strength_var.set("中等")
            self.strength_value.config(foreground="orange")
        elif strength <= 8:
            self.strength_var.set("强")
            self.strength_value.config(foreground="green")
        else:
            self.strength_var.set("非常强")
            self.strength_value.config(foreground="dark green")
        
    def copy_password(self):
        password = self.password_var.get()
        if password:
            self.root.clipboard_clear()
            self.root.clipboard_append(password)
            messagebox.showinfo("已复制", "密码已复制到剪贴板")
        else:
            messagebox.showwarning("警告", "没有生成密码")

if __name__ == "__main__":
    root = tk.Tk()
    app = PasswordGenerator(root)
    root.mainloop() 